using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class WeaponManager : SynchronizedGameObject
{
	private string _currentWeaponSlotName = string.Empty;

	public Dictionary<string, WeaponSlot> slots = new Dictionary<string, WeaponSlot>();

	public Transform weaponHolderRight;

	public Transform weaponHolderLeft;

	private PlayerBehavior player;

	private bool _enableWeaponChanged = true;

	private List<string> enableWeaponName = new List<string>();

	private bool LastShootState = true;

	private bool needSendSimpleShoot = true;

	private BaseWeapon lastSendedWeapon;

	private float lastPercent;

	public List<DistanceDamageModifier> distanceDamageModifiers;

	public string currentWeaponSlotName
	{
		get
		{
			return _currentWeaponSlotName;
		}
		set
		{
			if (_currentWeaponSlotName != value)
			{
				_currentWeaponSlotName = value;
				RiseEvent(this, "SlotChanged", _currentWeaponSlotName);
			}
		}
	}

	public WeaponSlot currentWeaponSlot
	{
		get
		{
			if (slots.ContainsKey(currentWeaponSlotName))
			{
				return slots[currentWeaponSlotName];
			}
			return null;
		}
		set
		{
			if (slots.ContainsKey(currentWeaponSlotName))
			{
				RefreshWeaponSubscription(false);
				currentWeaponSlotName = value.name;
				RefreshWeaponSubscription(true);
			}
		}
	}

	public BaseWeapon currentWeaponScript
	{
		get
		{
			if (slots.ContainsKey(currentWeaponSlotName))
			{
				return slots[currentWeaponSlotName].weapon;
			}
			return null;
		}
	}

	public bool EnableWeaponChanged
	{
		get
		{
			return _enableWeaponChanged;
		}
		set
		{
			if (value)
			{
			}
			_enableWeaponChanged = value;
		}
	}

	public void SetEnableWeapon(List<string> enableWeapon)
	{
		enableWeaponName = enableWeapon;
	}

	public override void Init()
	{
		base.Init();
		InitEvents(new string[3] { "SlotChanged", "WeaponChanged", "WeaponChangeVisiable" });
	}

	public override void Awake()
	{
		base.Awake();
		player = GetComponent<PlayerBehavior>();
	}

	public override void Start()
	{
		base.Start();
		if (Device.indexWeakDevice <= 0)
		{
			StartCoroutine(WeaponStatistick());
		}
	}

	public void AttachShopEvents()
	{
		MarketController.Instance.AddEventListener(this, "WeaponEquipped", delegate(Object sender, object[] args)
		{
			switchWeapon((string)args[0], (string)args[1], string.Empty);
		}, false);
		MarketController.Instance.AddEventListener(this, "WeaponUnEquipped", delegate(Object sender, object[] args)
		{
			switchWeapon((string)args[0], string.Empty, string.Empty);
		}, false);
		MarketController.Instance.AddEventListener(this, "SellectWeaponSlot", delegate(Object sender, object[] args)
		{
			ActivateWeaponSlot((string)args[0]);
		}, false);
		MarketController.Instance.AddEventListener(this, "ChangeConsumableCount", delegate(Object sender, object[] args)
		{
			RefreshWeaponAmmo((string)args[0]);
		}, false);
		if (GameController.instance.curTypeGame != TypeGame.CopsAndRobbers)
		{
			MarketController.Instance.GetStartWeapons();
		}
	}

	public void OnChangeAmmo()
	{
	}

	public void RefreshAmmo()
	{
		foreach (KeyValuePair<string, WeaponSlot> slot in slots)
		{
			if (slot.Value != null && slot.Value.weapon != null)
			{
				slot.Value.weapon.UpdateAmmo();
			}
		}
	}

	public void SetAllWeaponStartAmmo()
	{
		foreach (KeyValuePair<string, WeaponSlot> slot in slots)
		{
			if (slot.Value != null && slot.Value.weapon != null)
			{
				BulletCountSaver.SetStartAmmo(slot.Value.weapon);
			}
		}
	}

	public void RefreshWeaponAmmo(string weapon)
	{
		foreach (KeyValuePair<string, WeaponSlot> slot in slots)
		{
			if (slot.Value != null && slot.Value.weapon != null && slot.Value.weapon.name.Equals(weapon))
			{
				BulletCountSaver.SetStartAmmo(slot.Value.weapon);
			}
		}
	}

	public void Shoot(bool val, Vector3 point)
	{
		if (!(currentWeaponScript == null))
		{
			if (val)
			{
				currentWeaponScript.StartShoot(point);
			}
			else if (LastShootState)
			{
				StopOnlineShoot();
				currentWeaponScript.StopShoot();
			}
			LastShootState = val;
		}
	}

	public bool BulletIsEmpty()
	{
		if (currentWeaponScript != null)
		{
			return currentWeaponScript.ammo <= 0;
		}
		return true;
	}

	public void SetVisibleWeapon(bool val)
	{
		if (currentWeaponScript != null)
		{
			foreach (KeyValuePair<string, WeaponSlot> slot in slots)
			{
				slot.Value.SetVisiable(val);
			}
		}
		Renderer[] componentsInChildren = weaponHolderLeft.GetComponentsInChildren<Renderer>(true);
		foreach (Renderer renderer in componentsInChildren)
		{
			renderer.enabled = val;
		}
		Renderer[] componentsInChildren2 = weaponHolderRight.GetComponentsInChildren<Renderer>(true);
		foreach (Renderer renderer2 in componentsInChildren2)
		{
			renderer2.enabled = val;
		}
		RiseEvent(this, "WeaponChangeVisiable", val);
	}

	public void StopOnlineShoot()
	{
		if (currentWeaponScript != null && !settings.offlineMode && !base.photonView.isMine)
		{
			currentWeaponScript.StopOnlineShoot();
		}
	}

	[PunRPC]
	public void StartPool()
	{
		if (settings.offlineMode)
		{
			return;
		}
		if (base.photonView.isMine)
		{
			base.photonView.RPC("StartPool", PhotonTargets.Others);
			return;
		}
		if (currentWeaponScript != null)
		{
			currentWeaponScript.StartPool();
		}
		player.isShooting = true;
	}

	private void Update()
	{
		if (!needSendSimpleShoot && !currentWeaponScript.needShow)
		{
			StopOnlineShoot();
		}
	}

	public void SimpleShoot()
	{
		if (!settings.offlineMode && needSendSimpleShoot && !base.photonView.isMine && currentWeaponScript != null)
		{
			player.isShooting = true;
			currentWeaponScript.StartOnlineShoot(Vector3.zero);
		}
	}

	[PunRPC]
	public void SetAmmo(int val)
	{
		StartCoroutine(setAmmo(val));
	}

	public IEnumerator setAmmo(int val)
	{
		while (!(currentWeaponScript != null))
		{
			yield return null;
		}
		currentWeaponScript.chargerAmmo = val;
	}

	[PunRPC]
	public void SimpleReload(float time)
	{
		StopOnlineShoot();
		if (!settings.offlineMode)
		{
			if (base.photonView.isMine)
			{
				needSendSimpleShoot = true;
				base.photonView.RPC("SimpleReload", PhotonTargets.Others, currentWeaponScript.ReloadTime);
			}
			else if (currentWeaponScript != null)
			{
				currentWeaponScript.StartOnlineReload(time);
			}
		}
	}

	public void SetEquipedWeapon(string[] slotName, string[] weaponName, string[] defaultWeaponName)
	{
		for (int i = 0; i < slotName.Length; i++)
		{
			StartCoroutine(WaitAndCreateWeapon(slotName[i], weaponName[i], defaultWeaponName[i]));
		}
	}

	public void ManageHomingAim()
	{
		if (base.isMine && !player.inCar)
		{
			if (currentWeaponScript != null && currentWeaponScript.charge.type == ChargeType.Homing)
			{
				WeaponTargetDetector.instance.homingAim = true;
				WeaponTargetDetector.instance.StartWatchEnemyPlayers();
			}
			else
			{
				WeaponTargetDetector.instance.homingAim = false;
				WeaponTargetDetector.instance.StopWatchEnemyPlayers();
			}
		}
	}

	public void ActivateWeaponSlot(string slotName)
	{
		if (!EnableWeaponChanged && !enableWeaponName.Contains(slots[slotName].weaponName))
		{
			return;
		}
		RefreshWeaponSubscription(false);
		currentWeaponSlotName = slotName;
		RefreshWeaponSubscription(true);
		foreach (KeyValuePair<string, WeaponSlot> slot in slots)
		{
			slot.Value.SetActive(slot.Key == slotName);
		}
		ManageHomingAim();
	}

	[PunRPC]
	public void switchWeapon(string slotName, string weaponName, string defaultWeaponName = "")
	{
		if ((EnableWeaponChanged || enableWeaponName.Contains(weaponName)) && (!slots.ContainsKey(slotName) || slots[slotName] == null || !slots[slotName].weaponName.Equals(weaponName)))
		{
			StartCoroutine(WaitAndCreateWeapon(slotName, weaponName, defaultWeaponName));
		}
	}

	public void SendOnlineWeapon(bool force = false)
	{
		if (force)
		{
			lastSendedWeapon = null;
		}
		if (!settings.offlineMode && base.isMine && (bool)currentWeaponScript && lastSendedWeapon != currentWeaponScript)
		{
			lastSendedWeapon = currentWeaponScript;
			UpdateWeaponProps(currentWeaponScript.name, currentWeaponScript.defaultName);
			base.photonView.RPC("switchWeapon", PhotonTargets.Others, "Main", currentWeaponScript.name, currentWeaponScript.defaultName);
		}
	}

	private void UpdateWeaponProps(string weaponName, string defaultWeaponName)
	{
		PhotonNetwork.player.UpdateProperty(PlayerPropsKeys.weapon, weaponName);
		PhotonNetwork.player.UpdateProperty(PlayerPropsKeys.defaultWeapon, defaultWeaponName);
		PhotonNetwork.player.UpdateProperty(PlayerPropsKeys.hasWeapon, true);
	}

	public void SetWeaponFromProps(string weaponName, string weaponDefaultName, bool hasWeapon)
	{
		if (!settings.offlineMode && hasWeapon)
		{
			switchWeapon("Main", weaponName, weaponDefaultName);
		}
	}

	private IEnumerator WaitAndCreateWeapon(string slotName, string weaponName, string defaultWeaponName)
	{
		if (!slots.ContainsKey(slotName))
		{
			GameObject obj = new GameObject
			{
				name = slotName
			};
			slots.Add(slotName, obj.AddComponent<WeaponSlot>());
			obj.transform.parent = base.transform;
			if (slotName == "Main")
			{
				ActivateWeaponSlot(slotName);
			}
		}
		string slotName2 = default(string);
		slots[slotName].AddEventListener(this, "WeaponLoaded", delegate
		{
			InitWeapon(slots[slotName2].weapon);
			needSendSimpleShoot = true;
			if (GameController.instance.curTypeGame == TypeGame.Zombe && PlayerBehavior.MyPlayer.localTeam == PunTeams.Team.red)
			{
				slots[slotName2].weapon.damage = ((ZombeSettings)settings.GetSettings(TypeGame.Zombe)).zombieDamage;
			}
		});
		if (base.isMine)
		{
			slots[slotName].AddEventListener(this, "WeaponActivated", delegate
			{
				SendOnlineWeapon();
			});
		}
		slots[slotName].AddEventListener(this, "SlotSellected", delegate(Object slot, object[] slotArgs)
		{
			ActivateWeaponSlot(((WeaponSlot)slotArgs[0]).name);
			if ((bool)currentWeaponScript)
			{
				RiseEvent(this, "WeaponChanged", currentWeaponScript);
			}
		});
		slots[slotName].NewWeapon(weaponName, defaultWeaponName, base.isMine);
		yield return new WaitForEndOfFrame();
	}

	public void InitWeapon(BaseWeapon weapon)
	{
		if (player.inCar)
		{
			SetVisibleWeapon(false);
		}
		if (settings.offlineMode || base.photonView.isMine)
		{
			weapon.Init(GameController.instance.playerScript.weaponLayers, weaponHolderRight, weaponHolderLeft, GameController.instance.playerScript.bodyCollider);
			BulletCountSaver.OnChangeWeapon(weapon);
			weapon.AddEventListener(this, "ChangeStrength", delegate(Object sender, object[] args)
			{
				float num = (float)args[0];
				if (lastPercent == 0f && num > 0f)
				{
					StartPool();
				}
				lastPercent = num;
				WalkWindow.instance.weaponStrange.SetValue(num);
			}, false);
		}
		else
		{
			weapon.Init(GameController.instance.playerScript.weaponLayers, weaponHolderRight, weaponHolderLeft, GetComponentInChildren<Collider>());
		}
		weapon.AddEventListener(this, "ChangeAmmo", delegate
		{
			OnChangeAmmo();
		}, false);
		weapon.AddEventListener(this, "NoAmmo", delegate
		{
			StopOnlineShoot();
		}, false);
		weapon.AddEventListener(this, "OnlineShoot", delegate
		{
			SimpleShoot();
		}, false);
		weapon.AddEventListener(this, "OnlineReload", delegate
		{
			SimpleReload(currentWeaponScript.ReloadTime);
		}, false);
	}

	public bool isFullAmmo()
	{
		return currentWeaponScript.isFullAmmo();
	}

	public IEnumerator WeaponStatistick()
	{
		List<string> weaponsNameForFlurry = new List<string>();
		List<int> weaponsPopularityForFlurry = new List<int>();
		Save.SaveString(settings.KeyLastMap, SceneManager.GetActiveScene().name);
		if (settings.offlineMode)
		{
			Save.SaveString(settings.KeyLastGameMode, "PVE");
		}
		else if (GameController.instance.curTypeGame == TypeGame.deathmath)
		{
			Save.SaveString(settings.KeyLastGameMode, "PVP maps (total)");
		}
		else
		{
			Save.SaveString(settings.KeyLastGameMode, "PVP Sandbox");
		}
		yield return new WaitForSeconds(15f);
		while (true)
		{
			if (currentWeaponScript != null)
			{
				if (weaponsNameForFlurry.Contains(currentWeaponScript.name))
				{
					for (int i = 0; i < weaponsNameForFlurry.Count; i++)
					{
						if (weaponsNameForFlurry[i].Equals(currentWeaponScript.name))
						{
							List<int> list;
							List<int> list2 = (list = weaponsPopularityForFlurry);
							int index;
							int index2 = (index = i);
							index = list[index];
							list2[index2] = index + 1;
						}
					}
				}
				else
				{
					weaponsNameForFlurry.Add(currentWeaponScript.name);
					weaponsPopularityForFlurry.Add(1);
				}
				Save.SaveStringArray(settings.KeyTopUsedWeaponName, weaponsNameForFlurry.ToArray());
				Save.SaveIntArray(settings.KeyTopUsedWeaponCount, weaponsPopularityForFlurry.ToArray());
			}
			yield return new WaitForSeconds(15f);
		}
	}

	private void OnDestroy()
	{
		List<string> list = new List<string>();
		foreach (KeyValuePair<string, WeaponSlot> slot in slots)
		{
			list.Add(slot.Key);
		}
		for (int i = 0; i < list.Count; i++)
		{
			Object.Destroy(slots[list[i]]);
		}
	}

	public void RemoveAllWeapon()
	{
		foreach (KeyValuePair<string, WeaponSlot> slot in slots)
		{
			slot.Value.UnLoadWeapon();
		}
	}

	private void RefreshWeaponSubscription(bool subscribe)
	{
		if (base.isMine && currentWeaponScript != null)
		{
			currentWeaponScript.SubscribeForEvent(player, subscribe);
		}
	}

	public float GetDistanceDamageModifier(float distance)
	{
		float result = 1f;
		if (currentWeaponScript != null)
		{
			DistanceDamageModifier distanceDamageModifier = distanceDamageModifiers.Find((DistanceDamageModifier x) => x.buffableWeaponType == currentWeaponScript.buffableWeaponType);
			if (distanceDamageModifier != null)
			{
				int num = distanceDamageModifier.distanceDamageModifierSettings.FindLastIndex((DistanceDamageModifierSettings x) => x.maxDistance < distance);
				if (num > -1)
				{
					DistanceDamageModifierSettings distanceDamageModifierSettings = distanceDamageModifier.distanceDamageModifierSettings[num];
					if (num + 1 < distanceDamageModifier.distanceDamageModifierSettings.Count)
					{
						distanceDamageModifierSettings = distanceDamageModifier.distanceDamageModifierSettings[num + 1];
					}
					result = distanceDamageModifierSettings.damageModifier;
				}
				else
				{
					result = distanceDamageModifier.distanceDamageModifierSettings[0].damageModifier;
				}
			}
		}
		return result;
	}
}
